#include <stdlib.h>
#include <glut.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

GLfloat rotate;

struct vertex
{
	float x,y,z;
}vertexA[500];

struct face
{
	int a,b,c;
}faceA[500];

int counter=0;

void loadFile( char* filename )
{
	char line[255], comment[255];

	float x,y,z;
	FILE* file;
	int a,b,c;
	file = fopen( filename, "r" );


	int i=1;
	int j=1;
	while ( fgets( line, sizeof(line), file ) != NULL )
	{
		if (sscanf( line, "#%s", comment ) )
		printf( "valid: comment %s\n", comment );

		if (sscanf( line, "v %f %f %f", &x, &y, &z ) ) 
		{
			vertexA[i].x = x;
			vertexA[i].y = y; 
			vertexA[i].z = z;
			printf(" vertex x = %f ", vertexA[i].x); 
			printf(" vertex y = %f ", vertexA[i].y); 
			printf(" vertex z = %f \n\n", vertexA[i].z);
			i++;
		}

		if (sscanf( line, "f %i %i %i", &a, &b, &c ) )
		{
			faceA[j].a = a;
			faceA[j].b = b; 
			faceA[j].c = c;
			printf(" face a = %i ", faceA[j].a); 
			printf(" face b = %i ", faceA[j].b); 
			printf(" face c = %i \n\n", faceA[j].c);
			j++;
		}
	}
	counter = j;
	printf(" fc = %i \n\n", j);
}
void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);
   glEnable(GL_DEPTH_TEST);

   	GLfloat ambientL1[] = { 0.0, 1.0, 0.0, 1.0 };
	GLfloat diffuseL1[] = { 0.4, 0.7, 0.0, 0.5 };
	GLfloat specularL1[] = { 0.2, 1.0, 0.3, 1.0 };
	GLfloat positionL1[] = { 0.0, 10.5, 0.0, 1.0 };

	glLightfv(GL_LIGHT1, GL_AMBIENT, ambientL1);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseL1);
	glLightfv(GL_LIGHT1, GL_SPECULAR, specularL1);
	glLightfv(GL_LIGHT1, GL_POSITION, positionL1);

	
   	GLfloat ambientL2[] = { 1.0, 0.0, 0.0, 1.0 };
	GLfloat diffuseL2[] = { 0.8, 0.0, 0.0, 0.0 };
	GLfloat specularL2[] = { 0.4, 0.9, 0.0, 1.0 };
	GLfloat positionL2[] = { 10.5, 0.0, 0.0, 0.0 };

	glLightfv(GL_LIGHT2, GL_AMBIENT, ambientL2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuseL2);
	glLightfv(GL_LIGHT2, GL_SPECULAR, specularL2);
	glLightfv(GL_LIGHT2, GL_POSITION, positionL2);

	
   	GLfloat ambientL3[] = { 0.0, 0.0, 0.0, 1.0 };
	GLfloat diffuseL3[] = { 0.0, 0.7, 0.0, 0.0 };
	GLfloat specularL3[] = { 0.9, 0.0, 0.3, 1.0 };
	GLfloat positionL3[] = { -5.0, 0.0, 5.0, 1.0 };

    float LightDir[3] = {0.0f,0.0f,-1.0f};
	glLighti(GL_LIGHT3, GL_SPOT_CUTOFF,30);
	glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, LightDir);
	glLightfv(GL_LIGHT3, GL_AMBIENT, ambientL3);
	glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuseL3);
	glLightfv(GL_LIGHT3, GL_SPECULAR, specularL3);
	glLightfv(GL_LIGHT3, GL_POSITION, positionL3);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT1);
    glEnable(GL_LIGHT2);
    glEnable(GL_LIGHT3);
	glShadeModel(GL_SMOOTH);


}
void DoerrTimDisplay(void)
{
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity ();
   gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
   glRotatef (rotate, 0.0, 1.0, 0.0);
   glPushMatrix();

   	GLuint objModel = glGenLists(1);
	glNewList( objModel, GL_COMPILE );
	glBegin( GL_TRIANGLES );

	for (int i = 1; i < counter+1; i++)
	{
	glVertex3f( vertexA[faceA[i].a].x, vertexA[faceA[i].a].y, vertexA[faceA[i].a].z);
	glVertex3f( vertexA[faceA[i].b].x, vertexA[faceA[i].b].y, vertexA[faceA[i].b].z);
	glVertex3f( vertexA[faceA[i].c].x, vertexA[faceA[i].c].y, vertexA[faceA[i].c].z);
	}

    glEnd();
	glEndList();
	glCallList(objModel);

   /*Auskomentierter Baum
   // WÃœrfel 1 (Stamm)
   glColor3f (1.0, 1.0, 1.0);
   glLoadIdentity ();
   glPopMatrix();
   glPushMatrix();
   glTranslatef (0.0, -1.0, 0.0); 
   glScalef (1.0, 2.0, 1.0); 
   glutSolidCube (1.0);		
   //WÃ¼rfel 2 (Ast 1)
   glColor3f (0.0, 0.7, 1.0);
   glLoadIdentity ();
   glPopMatrix();
   glPushMatrix();
   glRotatef (60, 0.0, 0.0, 1.0);
   glTranslatef (0.0, 1.0, 0.0); 
   glScalef (1.0, 2.0, 1.0); 
   glutSolidCube (1.0);		 
   //WÃ¼rfel 2 (Ast 1)
   glColor3f (0.7, 0.0, 1.0);
   glLoadIdentity ();
   glPopMatrix();
   glPushMatrix();
   glRotatef (120, 0.0, 1.0, 0.0);
   glRotatef (60, 0.0, 0.0, 1.0);
   glTranslatef (0.0, 1.0, 0.0); 
   glScalef (1.0, 2.0, 1.0); 
   glutSolidCube (1.0);		

   //WÃ¼rfel 3 (Ast 1)
   glColor3f (1.0, 0.7, 0.0);
   glLoadIdentity ();
   glPopMatrix();
   glRotatef (-120, 0.0, 1.0, 0.0);
   glRotatef (60, 0.0, 0.0, 1.0);
   glTranslatef (0.0, 1.0, 0.0); 
   glScalef (1.0, 2.0, 1.0); 
   glutSolidCube (1.0);		 
   */
   glFlush ();
}
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
   glMatrixMode (GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}
void idle (void)
{
	rotate+=0.02;
	glutPostRedisplay();
}
int main(int argc, char** argv)
{
   loadFile( "kasten.obj");
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);  
   init ();
   glutDisplayFunc(DoerrTimDisplay);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutIdleFunc(idle);
   glutMainLoop();
   return 0;
} 
